# 通行记录

from plugin import Mylogger, MSsqlClient, Config, MyTime
from module.huada.entity.virtualcard_entity import virtual_card_cache
from base import MY_STORED_CACHE, UPDATE_MY_STORED_CACHE
from config import Config
# ### 开门
# 2	首卡开门
# 4	刷卡开门
# 5	密码开门
# 35	卡与密码开门
# 37	考勤开门
# 42	胁迫开门
# 43	胁迫出门
# 60	刷脸开门
# 61	身份证开门
# 65	二维码开门
# 15	门常开，密码开门无效
open_door_events = [2, 4, 5, 35, 37, 42, 43, 60, 61, 65, 15]
# #### 1.凭据非法
# 32	挂失卡，刷卡无效
# 13	非法卡，刷卡无效
# 40	卡片未启用
# 62	非法人脸,开门无效
# 66	非法二维码
# #### 2.无权限
# 16	未授权，刷卡无效
# 63	未授权人脸,开门无效
# 67	二维码未启用
# #### 3.时段无权
# 18	禁行时段，刷卡无效
# #### 5.凭据过期
# 19	临时卡失效
# 68	过期二维码
# #### 7.门常闭未通过
# 14	门常闭，刷卡无效
# #### 8.用户密码错误
# 31	密码错误，开门无效
# 45	卡与密码开门无效
# #### 9.互锁未通过
# 44	互锁门，不能开门
# #### 499.其他原因
# 17	安全级别限制，刷卡无效
# 33	卡模式，密码开门无效
# 34	密码模式，刷卡无效
# 38	门模式错误
fail_reasons = {
    32: 1,
    13: 1,
    40: 1,
    62: 1,
    66: 1,
    16: 2,
    63: 2,
    67: 2,
    18: 3,
    19: 5,
    68: 5,
    14: 7,
    31: 8,
    45: 8,
    44: 9,
    17: 499,
    33: 499,
    34: 499,
    38: 499
}

sql = """
select * from
(
select 
    a.id as eventExtKey,
    a.time as eventTime,
    {3} as dataSysCode,
    c.addr,
    f.idtype,
    a.eventvalue,
    a.eventno,
    e.descr,
    '' as empName,
    '' as empExtKey,
    a.creationtime
from        acscon_ioeventlog_m{0} a 
inner join  acscon_realnode      c  on a.addr = c.addr
inner join  acscon_iotype        d  on c.iotypeid = d.id
inner join  acscon_ioevent       e  on a.eventno = e.eventno  and  c.iotypeid = e.iotypeid
inner join  acscon_card          f  on a.eventvalue = f.cardno
where triggerid ='' and d.descr like '%{1}%' and a.creationtime > '{2}'

union

select 
    a.id as eventExtKey,
    a.time as eventTime,
    {3} as dataSysCode,
    c.addr,
    f.idtype,
    a.eventvalue,
    a.eventno,
    e.descr,
    b.name as empName,
    b.usercode as empExtKey,
    a.creationtime
from        acscon_ioeventlog_m{0} a 
inner join  acscon_realnode      c  on a.addr = c.addr
inner join  acscon_iotype        d  on c.iotypeid = d.id
inner join  acscon_ioevent       e  on a.eventno = e.eventno  and  c.iotypeid = e.iotypeid
inner join  acscon_card          f  on a.eventvalue = f.cardno
left join  acscon_user           b  on a.triggerid = b.id
where triggerid <>'' and d.descr like '%{1}%'  and a.creationtime > '{2}'
)bb
order by creationtime desc
"""


class AccessRecordsEntity():
    url = "tunion/put/doorsthrough"
    table_name = "access_records"
    get_time = "2020-01-01 00:00:00"
    order_by = "modifyTime"
    get_datas = []
    # send_datas = []
    wirte_back_datas = []
    create_table = True

    def __init__(self, **kwargs) -> None:
        self.eventExtKey = kwargs.get('eventExtKey')  # 事件主键
        self.eventTime = kwargs.get('eventTime')  # 事件时间
        self.dataSysCode = kwargs.get('dataSysCode')  # 数据系统编码
        self.pointExtKey = kwargs.get('pointExtKey')  # 门禁点主键
        self.proofType = kwargs.get('proofType')  # 证件类型 0-保留 1-卡片 2-人脸 4-指纹 8-二维码
        self.proofNo = kwargs.get('proofNo')  # 证件号码
        # 识别方式 0-成功 1-刷卡 2-刷脸 3-刷卡加人脸 4-刷指纹 8-刷二维码
        self.verifyType = kwargs.get('verifyType')
        self.empExtKey = kwargs.get('empExtKey')  # 员工主键
        self.empName = kwargs.get('empName')  # 员工姓名
        self.empCode = kwargs.get('empCode')  # 员工编号
        self.empType = kwargs.get('empType')  # 员工类型 default 11
        self.inOutFlag = kwargs.get('inOutFlag')  # 进出标志 0-不区分 1-进 2-出 3-进出
        self.isValid = kwargs.get('isValid')  # 是否通过 0-无 1-有
        self.failReason = kwargs.get('failReason')  # 失败原因
        self.modifyTime = kwargs.get('modifyTime')  # 修改时间
        self.id = kwargs.get('id') or 0  # 序号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理

    @classmethod
    def get_data(cls):
        if not MY_STORED_CACHE.__contains__(cls.table_name + "_get_time"):
            # MY_STORED_CACHE[cls.table_name + "_get_time"] = cls.get_time
            UPDATE_MY_STORED_CACHE(cls.table_name + "_get_time", cls.get_time)
        get_time = MY_STORED_CACHE[cls.table_name + "_get_time"]
        client = MSsqlClient(charset='cp936', **Config.module_config.huada.client_link)
        results = client.select_to_dict(sql.format(MyTime.get_date_part('MM'), 'rd', get_time, Config.module_config.huada.system_code))
        next_req_time = MyTime.timestr()  # 下次请求时间
        if results and len(results) > 0:
            for result in results:
                try:
                    result["pointExtKey"] = get_point_ext_key(result["addr"])
                    if result["pointExtKey"] is None:
                        continue
                    result["proofType"] = get_proof_type(result["idtype"])

                    if result["proofType"] != 1 and virtual_card_cache.__contains__(result["empExtKey"]):
                        # 非卡凭证，并且有缓存，获取虚拟卡号
                        result["proofNo"] = virtual_card_cache[result["empExtKey"]].empUCode
                    elif result["proofType"] == 1:
                        # 如果result["proofType"]=1，将16进制result["eventvalue"]转成10进制
                        result["proofNo"] = str(int(result["eventvalue"], 16))

                    # result['proofNo'] = result["eventvalue"]
                    result["verifyType"] = result["proofType"]
                    result['empCode'] = result['empExtKey']
                    # 如果是员工（BGI开头），则将员工类型设置为11，否则设置为12
                    result['empType'] = 11 if result['empCode'][:3].upper() == "BGI" else 12
                    # print('123BGI'.lower())
                    result['inOutFlag'] = 0
                    result['isValid'] = 1 if result['eventno'] in open_door_events else 0
                    result['failReason'] = fail_reasons.get(result['eventno'], 0)
                    result['modifyTime'] = result['creationtime']
                    cls.get_datas.append(cls(**result))
                except Exception as e:
                    Mylogger.error(f"解析通行记录失败，卡号没有对应人员，{result}")

        record_client = MSsqlClient(**Config.module_config.huada.record_link)
        if cls.create_table:
            # 获取类的成员变量
            fields = [i for i in cls().__dict__.keys() if not i.startswith('_') and i != "id"]
            record_client.create_table(cls.table_name, fields, id_increment=True, create_time=True)
            Mylogger.info(f"create table {cls.table_name} success")
            cls.create_table = False
        objs = cls.get_datas.copy()  # 拷贝一份, 防止多线程操作
        Mylogger.info(f"save {len(objs)} records to {cls.table_name}")
        # 去掉id字段
        for obj in objs:
            del obj.id
        if record_client.insert_objects(objs, cls.table_name):
            Mylogger.info(f"save {len(objs)} records to {cls.table_name} success")
            # 计算差集
            cls.get_datas = list(set(cls.get_datas).difference(set(objs)))
            # MY_STORED_CACHE[cls.table_name + "_get_time"] = next_req_time  # 插入成功后更新下次请求时间
            UPDATE_MY_STORED_CACHE(cls.table_name + "_get_time", next_req_time)  # 插入成功后更新下次请求时间

    @classmethod
    def send_data(cls, url, data):
        from base import requests
        client = MSsqlClient(charset='cp936', **Config.module_config.huada.record_link)
        results = client.select_to_dict(f"select * from {cls.table_name} where isdeal = 0 order by {cls.order_by}")
        Mylogger.info(f"get {len(results)} records from {cls.table_name}")
        if results and len(results) > 0:
            # 每100条数据发送一次
            send_datas = []
            ids = []
            for result in results:
                obj = cls(**result)
                del obj.id
                del obj.isdeal
                send_datas.append(obj.__dict__)
                ids.append(str(result['id']))
                if len(send_datas) == 100 or result == results[-1]:
                    data['data'] = send_datas
                    res = requests.post(url + cls.url, json=data)
                    send_datas.clear()
                    if res.status_code == 200:
                        r = res.json()
                        if r.__contains__("code") and r["code"] == 200:
                            # 更新已发送的数据
                            client.execute("update {} set isdeal = 1 where id in ('{}')".format(cls.table_name, "','".join(ids)))
                            Mylogger.info(f"发送{len(ids)}条数据成功")
                        else:
                            Mylogger.error(f"发送数据失败, {r}")
                    else:
                        Mylogger.error(f"发送数据失败, {res.text}")
                    ids.clear()
            send_datas.clear()





def get_proof_type(idtype):
    # idtype: 0-卡 1-指纹 2-身份证 5-人脸 8-二维码
    # proof_type 0-保留 1-卡片 2-人脸 4-指纹 8-二维码
    if idtype == 0:
        return 1
    elif idtype == 1:
        return 4
    elif idtype == 5:
        return 2
    elif idtype == 8:
        return 8
    return 0


def get_verify_type(eventno):
    if eventno in open_door_events:
        return 0


def get_point_ext_key(addr):
    addr = addr.replace('#', '-')
    addrs = addr.split('-')
    door_channel = int(addr[-1])  # 获取门点最后一位
    diff = 0
    if door_channel in (3,4):
        diff  = 2
    elif door_channel in (5,6,7,8):
        diff = 4
    else:
        return None
    
    addrs[-1] = str(door_channel - diff)  # 根据读头获取门点
    # 每一位前面补零，到3位，然后拼接
    addrs = [str(i).zfill(3) for i in addrs]
    return str(Config.module_config.huada.system_code) + '-' + ''.join(addrs)

if __name__ == '__main__':
    get_point_ext_key('100-1#2-1')